package com.cupk.services;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 文件服务类
 */
@Slf4j
@Service
public class FileService {

    @Value("${file.upload.dir:uploads}")
    private String uploadDir;

    @Value("${file.max.size:10485760}") // 10MB
    private long maxFileSize;

    private final Path fileStorageLocation;

    public FileService(@Value("${file.upload.dir:uploads}") String uploadDir) {
        this.fileStorageLocation = Paths.get(uploadDir).toAbsolutePath().normalize();
        
        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            throw new RuntimeException("无法创建文件上传目录", ex);
        }
    }

    /**
     * 上传文件
     */
    public String uploadFile(MultipartFile file, String category, String username) {
        // 验证文件
        validateFile(file);
        
        // 生成唯一文件名
        String fileName = generateFileName(file.getOriginalFilename());
        
        try {
            // 创建分类目录
            Path categoryPath = this.fileStorageLocation.resolve(category);
            Files.createDirectories(categoryPath);
            
            // 保存文件
            Path targetLocation = categoryPath.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            
            log.info("文件上传成功: {}, 用户: {}", fileName, username);
            
            // 返回文件访问URL
            return "/files/preview/" + category + "/" + fileName;
            
        } catch (IOException ex) {
            throw new RuntimeException("文件存储失败: " + fileName, ex);
        }
    }

    /**
     * 加载文件资源
     */
    public Resource loadFileAsResource(String fileName) {
        try {
            Path filePath = resolveFilePath(fileName);
            Resource resource = new UrlResource(filePath.toUri());
            
            if (resource.exists()) {
                return resource;
            } else {
                throw new RuntimeException("文件不存在: " + fileName);
            }
        } catch (MalformedURLException ex) {
            throw new RuntimeException("文件路径错误: " + fileName, ex);
        }
    }

    /**
     * 删除文件
     */
    public void deleteFile(String fileName, String username) {
        try {
            Path filePath = resolveFilePath(fileName);
            Files.deleteIfExists(filePath);
            log.info("文件删除成功: {}, 用户: {}", fileName, username);
        } catch (IOException ex) {
            throw new RuntimeException("文件删除失败: " + fileName, ex);
        }
    }

    /**
     * 获取文件信息
     */
    public Map<String, Object> getFileInfo(String fileName) {
        try {
            Path filePath = resolveFilePath(fileName);
            
            if (!Files.exists(filePath)) {
                throw new RuntimeException("文件不存在: " + fileName);
            }
            
            Map<String, Object> fileInfo = new HashMap<>();
            fileInfo.put("fileName", fileName);
            fileInfo.put("fileSize", Files.size(filePath));
            fileInfo.put("contentType", getContentType(fileName));
            fileInfo.put("lastModified", Files.getLastModifiedTime(filePath).toString());
            
            return fileInfo;
        } catch (IOException ex) {
            throw new RuntimeException("获取文件信息失败: " + fileName, ex);
        }
    }

    /**
     * 获取文件内容类型
     */
    public String getContentType(String fileName) {
        String extension = getFileExtension(fileName).toLowerCase();
        
        switch (extension) {
            case "pdf":
                return "application/pdf";
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt":
                return "application/vnd.ms-powerpoint";
            case "pptx":
                return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            case "txt":
                return "text/plain";
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            default:
                return "application/octet-stream";
        }
    }

    /**
     * 验证文件
     */
    private void validateFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new RuntimeException("文件不能为空");
        }
        
        if (file.getSize() > maxFileSize) {
            throw new RuntimeException("文件大小超过限制: " + (maxFileSize / 1024 / 1024) + "MB");
        }
        
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        if (fileName.contains("..")) {
            throw new RuntimeException("文件名包含非法字符: " + fileName);
        }
        
        // 检查文件类型
        String extension = getFileExtension(fileName);
        if (!isAllowedFileType(extension)) {
            throw new RuntimeException("不支持的文件类型: " + extension);
        }
    }

    /**
     * 生成唯一文件名
     */
    private String generateFileName(String originalFileName) {
        String extension = getFileExtension(originalFileName);
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        return timestamp + "_" + uuid + "." + extension;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || fileName.lastIndexOf(".") == -1) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 检查是否为允许的文件类型
     */
    private boolean isAllowedFileType(String extension) {
        String[] allowedTypes = {
            "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", 
            "txt", "jpg", "jpeg", "png", "gif"
        };
        
        for (String type : allowedTypes) {
            if (type.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 解析文件路径
     */
    private Path resolveFilePath(String fileName) {
        // 处理带分类的文件名，如 "publication/filename.pdf"
        return this.fileStorageLocation.resolve(fileName).normalize();
    }
}
